﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using ICSharpCode.SharpZipLib.Zip;
using COM.Web;
using ICSharpCode.SharpZipLib.GZip;
using WebApp.Web.Service;
using COM.Data;
using Gma.QrCodeNet.Encoding;
using Gma.QrCodeNet.Encoding.Windows.Render;
using System.IO;
using COM.Service;

namespace WebApp.Web.Controllers
{
    public class BarCode2DController : Controller
    {
        public ActionResult DownloadPageUrl(string id)
        {
            var configService = COM.Web.Unity.Instance.GetService<IConfigService>();
            var downloadPageUrl = string.Format("http://{0}/{1}", configService.DeployHostName, id);
            // Retrieve the parameters from the QueryString
            var codeParams = CodeDescriptor.Init(downloadPageUrl);
            if (codeParams == null || !codeParams.TryEncode())
            {
                return null;
            }

            // Render the QR code as an image
            var ms = new MemoryStream();
            codeParams.Render(ms);
            ms.Position = 0;
            return File(ms, "image/png", id.ToString() + System.IO.Path.GetExtension("a.jpg"));
        }
    }

    /// <summary>
    /// Class containing the description of the QR code and wrapping encoding and rendering.
    /// </summary>
    internal class CodeDescriptor
    {
        public ErrorCorrectionLevel Ecl;
        public string Content;
        public QuietZoneModules QuietZones;
        public int ModuleSize;
        public BitMatrix Matrix;

        /// <summary>
        /// Parse QueryString that define the QR code properties
        /// </summary>
        /// <param name="request">HttpRequest containing HTTP GET data</param>
        /// <returns>A QR code descriptor object</returns>
        public static CodeDescriptor Init(string content, string e = "M", string q = "Two", string s = "12")
        {
            var cp = new CodeDescriptor();

            // Error correction level
            if (!Enum.TryParse(e, out cp.Ecl))
                cp.Ecl = ErrorCorrectionLevel.L;

            // Code content to encode
            cp.Content = content;

            // Size of the quiet zone
            if (!Enum.TryParse(q, out cp.QuietZones))
                cp.QuietZones = QuietZoneModules.Two;

            // Module size
            if (!int.TryParse(s, out cp.ModuleSize))
                cp.ModuleSize = 12;

            return cp;
        }

        /// <summary>
        /// Encode the content with desired parameters and save the generated Matrix
        /// </summary>
        /// <returns>True if the encoding succeeded, false if the content is empty or too large to fit in a QR code</returns>
        public bool TryEncode()
        {
            var encoder = new QrEncoder(Ecl);
            QrCode qr;
            if (!encoder.TryEncode(Content, out qr))
                return false;

            Matrix = qr.Matrix;
            return true;
        }

        /// <summary>
        /// Render the Matrix as a PNG image
        /// </summary>
        /// <param name="ms">MemoryStream to store the image bytes into</param>
        internal void Render(MemoryStream ms)
        {
            var render = new GraphicsRenderer(new FixedModuleSize(ModuleSize, QuietZones));
            render.WriteToStream(Matrix, System.Drawing.Imaging.ImageFormat.Png, ms);
        }
    }

}
